package com.ete.service.util

import com.ete.service.callback.version.DownloadListener
import com.ete.service.net.api.ServiceApi
import com.ete.service.net.http.RetrofitClient
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.ResponseBody
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.io.*


/**
 * @author chenxiaojin
 * @date 2023/10/16
 */
object DownloadUtil {

    @JvmStatic
    fun download(url: String, path: String, downloadListener: DownloadListener) {
        val service: ServiceApi = RetrofitClient.createService(ServiceApi::class.java)
        val call: Call<ResponseBody> = service.download(url)
        downloadListener.onStart()
        call.enqueue(object : Callback<ResponseBody> {
            override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
                //将Response写入到从磁盘中，详见下面分析
                //注意，这个方法是运行在子线程中的
                CoroutineScope(Dispatchers.IO).launch {
                    writeResponseToDisk(path, response, downloadListener)
                }
            }

            override fun onFailure(call: Call<ResponseBody>, throwable: Throwable) {
                CoroutineScope(Dispatchers.Main).launch {
                    downloadListener.onFail("${throwable.message} ")
                }
            }
        })
    }

    private fun writeResponseToDisk(
            path: String,
            response: Response<ResponseBody>?,
            downloadListener: DownloadListener
    ) {
        //从response获取输入流以及总大小
        writeFileFromIS(
                File(path),
                response?.body()?.byteStream(),
                response?.body()?.contentLength(),
                downloadListener
        )
    }

    private const val sBufferSize = 8192

    //将输入流写入文件
    private fun writeFileFromIS(
            file: File,
            `is`: InputStream?,
            totalLength: Long?,
            downloadListener: DownloadListener
    ) {
        if (`is` == null || totalLength == null || totalLength <= 0) {
            CoroutineScope(Dispatchers.Main).launch {
                downloadListener.onFail("获取下载文件错误，请稍候重试...")
            }
            return
        }

        //创建文件
        if (!file.exists()) {
            if (!file.parentFile?.exists()!!) file.parentFile?.mkdir()
            try {
                file.createNewFile()
            } catch (e: IOException) {
                e.printStackTrace()
                CoroutineScope(Dispatchers.Main).launch {
                    downloadListener.onFail("创建文件错误，确认是否开启存储权限？")
                }
            }
        }
        var os: OutputStream? = null
        var currentLength: Long = 0
        try {
            os = BufferedOutputStream(FileOutputStream(file))
            val data = ByteArray(sBufferSize)
            var len: Int
            while (`is`.read(data, 0, sBufferSize).also { len = it } != -1) {
                os.write(data, 0, len)
                currentLength += len.toLong()
                //计算当前下载进度
                CoroutineScope(Dispatchers.Main).launch {
                    downloadListener.onProgress(
                            totalLength,
                            currentLength,
                            (100 * currentLength / totalLength).toInt()
                    )
                }
            }
            os.flush()
            os.close()
            //下载完成，并返回保存的文件路径
            CoroutineScope(Dispatchers.Main).launch { downloadListener.onFinish(file) }
        } catch (e: IOException) {
            e.printStackTrace()
            CoroutineScope(Dispatchers.Main).launch { downloadListener.onFail("下载异常:${e.message}") }
        } finally {
            try {
                `is`.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }
            try {
                os?.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
    }
}